﻿namespace FallingWordsGame
{
    using System;
    using System.Collections.Generic;
    using System.IO;

    using FallingWordsGame.Interfaces;
    
    public class BlockReader
    {
        private readonly string destination;
        private readonly StreamReader reader;
        private readonly IList<IWord> inCaseOfErrorBlocks;

        private readonly bool errorOccured;
        private int indexInCaseOfError;

        public BlockReader(string dest)
        {
            errorOccured = false;
            destination = dest;
            try
            {
                reader = new StreamReader(destination);
            }
            catch (FileNotFoundException)
            {
                Console.Error.WriteLine("File {0} can does not exist.",
                    destination.Substring(destination.LastIndexOf('/') + 1));
                errorOccured = true;
            }
            catch (DirectoryNotFoundException)
            {
                Console.Error.WriteLine("Destination path {0} is not a valid path",
                    destination.Substring(0, destination.LastIndexOf('/')));
                errorOccured = true;
            }
            catch (IOException)
            {
                Console.Error.WriteLine("Can not read from file {0} because of I/O error",
                    destination.Substring(destination.LastIndexOf('/') + 1));
                errorOccured = true;
            }
            finally
            {
                if (errorOccured)
                {
                    Console.WriteLine("The boss block will be created manually");
                    System.Threading.Thread.Sleep(3000);
                    inCaseOfErrorBlocks = new List<IWord>()
                        {                            
                            new Word("sometimes in the computer can occure an error"),
                            new Word("for some one it can be terrifying shock"),
                            new Word("but dont be affraid and run in terror"),
                            new Word("just use try catch block")
                        }; // LOL
                    indexInCaseOfError = 0;
                }
            }
        }

        public bool End()
        {
            if (errorOccured)
            {
                return indexInCaseOfError == inCaseOfErrorBlocks.Count;
            }
            else
            {
                return reader.EndOfStream;
            }
        }

        private IList<IWord> NextBlock()
        {
            if (errorOccured)
            {
                this.indexInCaseOfError++;
                return inCaseOfErrorBlocks;
            }
            else
            {
                IList<IWord> block = new List<IWord>();
                string line = reader.ReadLine();
                while (line != "@")
                {
                    block.Add(new Word(line));
                    line = reader.ReadLine();
                }
                return block;
            }
        }

        public IList<IList<IWord>> AllBlocks()
        {
            List<IList<IWord>> blocks = new List<IList<IWord>>();

            while(!this.reader.EndOfStream)
            {
                blocks.Add(NextBlock());
            }

            return blocks;
        }
    }
}